package com.gitee.wsl.text

/*****************************************************************************
 * ------------------------------------------------------------------------- *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/

/*
import com.gitee.wsl.base.BiOptional
import com.gitee.wsl.base.Both
import com.gitee.wsl.base.Predicate
import com.gitee.wsl.text.Substring.SubPattern

import java.util.Objects
import java.util.Optional
import java.util.Spliterator
import java.util.function.Consumer
import java.util.function.Function
import java.util.function.Predicate
import java.util.function.Supplier
import java.util.regex.Pattern
import java.util.stream.Collector
import java.util.stream.Stream
import java.util.stream.StreamSupport
import kotlin.math.max
import kotlin.math.min


*/
/**
 * Utilities for creating patterns that attempt to match a substring in an input string. The matched
 * substring can be [extracted][SubPattern.from], [removed][SubPattern.removeFrom], [ ][SubPattern.replaceFrom], or used to divide the input string into parts.
 *
 *
 * For example, to strip off the "http://" prefix from a uri string if present:
 *
 * <pre>
 * static String stripHttp(String uri) {
 * return Substring.prefix("http://").removeFrom(uri);
 * }
</pre> *
 *
 * To strip off either an "http://" or "https://" prefix if present:
 *
 * <pre>
 * static import com.google.util.Substring.prefix;
 *
 * static String stripHttpOrHttps(String uri) {
 * return prefix("http://").or(prefix("https://")).removeFrom(uri);
 * }
</pre> *
 *
 * To strip off a suffix starting with a dash (-) character:
 *
 * <pre>
 * static String stripDashSuffix(String str) {
 * return last('-').toEnd().removeFrom(str);
 * }
</pre> *
 *
 * To replace a trailing "//" with "/":
 *
 * <pre>
 * static String fixTrailingSlash(String str) {
 * return Substring.suffix("//").replaceFrom(str, '/');
 * }
</pre> *
 *
 * To extract the 'name' and 'value' from an input string in the format of "name:value":
 *
 * <pre>
 * Substring.first(':')
 * .split("name:joe")
 * .map(NameValue::new)
 * .orElseThrow(BadFormatException::new);
</pre> *
 *
 * To parse key-value pairs:
 *
 * <pre>`import static com.google.mu.util.stream.GuavaCollectors.toImmutableListMultimap;
 *
 * ImmutableListMultimap<String, String> tags =
 * first(',')
 * .repeatedly()
 * .splitThenTrimKeyValuesAround(first('='), "k1=v1, k2=v2")  // => [(k1, v1), (k2, v2)]
 * .collect(toImmutableListMultimap());
`</pre> *
 *
 * To replace the placeholders in a text with values (although do consider using a proper templating
 * framework because it's a security vulnerability if your values come from untrusted sources like
 * the user inputs):
 *
 * <pre>`ImmutableMap<String, String> variables =
 * ImmutableMap.of("who", "Arya Stark", "where", "Braavos");
 * String rendered =
 * spanningInOrder("{", "}")
 * .repeatedly()
 * .replaceAllFrom(
 * "{who} went to {where}.",
 * placeholder -> variables.get(placeholder.skip(1, 1).toString()));
 * assertThat(rendered).isEqualTo("Arya Stark went to Braavos.");
`</pre> *
 *
 * @since 2.0
 *//*

object Substring {
    */
/** `Pattern` that never matches any substring.  *//*

    val NONE: SubPattern = object : SubPattern() {
        override fun match(s: String, fromIndex: Int): SubPatternMatch? {
            return null
        }

        override fun toString(): String {
            return "NONE"
        }
    }

    */
/**
     * `Pattern` that matches the empty substring at the beginning of the input string.
     * Typically used to represent an optional delimiter. For example, the following pattern matches
     * the substring after optional "header_name=":
     *
     * <pre>
     * static final Substring.Pattern VALUE = Substring.after(first('=').or(BEGINNING));
    </pre> *
     *//*

    val BEGINNING: SubPattern = object : SubPattern() {
        override fun match(str: String, fromIndex: Int): SubPatternMatch {
            return SubPatternMatch.nonBacktrackable(str, fromIndex, 0)
        }

        override fun toString(): String {
            return "BEGINNING"
        }
    }

    */
/**
     * `Pattern` that matches the empty substring at the end of the input string. Typically used
     * to represent an optional delimiter. For example, the following pattern matches the text between
     * the first occurrence of the string "id=" and the end of that line, or the end of the string:
     *
     * <pre>
     * static final Substring.Pattern ID =
     * Substring.between(substring("id="), substring("\n").or(END));
    </pre> *
     *//*

    val END: SubPattern = object : SubPattern() {
        override fun match(str: String, fromIndex: Int): SubPatternMatch {
            return SubPatternMatch.suffix(str, 0)
        }

        override fun toString(): String {
            return "END"
        }
    }

    */
/**
     * Returns a `Prefix` pattern that matches strings starting with `prefix`.
     *
     *
     * Typically if you have a `String` constant representing a prefix, consider to declare a
     * [Prefix] constant instead. The type is more explicit, and utilitiy methods like [ ][SubPattern.removeFrom], [SubPattern.from] are easier to discover and use.
     *//*

    fun prefix(prefix: String): Prefix {
        return Prefix(Objects.requireNonNull(prefix))
    }

    */
/**
     * Returns a `Prefix` pattern that matches strings starting with `prefix`.
     *
     *
     * Typically if you have a `char` constant representing a prefix, consider to declare a
     * [Prefix] constant instead. The type is more explicit, and utilitiy methods like [ ][SubPattern.removeFrom], [SubPattern.from] are easier to discover and use.
     *//*

    fun prefix(prefix: Char): Prefix {
        return Prefix(prefix.toString())
    }

    */
/**
     * Returns a `Suffix` pattern that matches strings ending with `suffix`.
     *
     *
     * Typically if you have a `String` constant representing a suffix, consider to declare a
     * [Suffix] constant instead. The type is more explicit, and utilitiy methods like [ ][SubPattern.removeFrom], [SubPattern.from] are easier to discover and use.
     *//*

    fun suffix(suffix: String): Suffix {
        return Suffix(suffix)
    }

    */
/**
     * Returns a `Suffix` pattern that matches strings ending with `suffix`.
     *
     *
     * Typically if you have a `char` constant representing a suffix, consider to declare a
     * [Suffix] constant instead. The type is more explicit, and utilitiy methods like [ ][SubPattern.removeFrom], [SubPattern.from] are easier to discover and use.
     *//*

    fun suffix(suffix: Char): Suffix {
        return Suffix(suffix.toString())
    }

    */
/** Returns a `Pattern` that matches the first occurrence of `str`.  *//*

    fun first(str: String): SubPattern {
        return if (str.length == 1) {
            first(str[0])
        } else object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                val index = input.indexOf(str, fromIndex)
                return if (index >= fromIndex) SubPatternMatch.backtrackable(
                    1,
                    input,
                    index,
                    str.length
                ) else null
            }

            override fun lookaround(lookbehind: String, lookahead: String): SubPattern {
                // first(lookbehind + str).skip(lookbehind) is more efficient with native String#indexOf().
                //
                // Can't use first(lookbehind + str + lookbehind).skip(lookbehind, lookahead)
                // because skip().repeatedly() will repeat after `lookahead`.
                // between(lookbehind, lookahead).repeatedly() should repeat _at_ `lookahead`.
                return if (lookbehind.isEmpty()) super.lookaround(lookbehind, lookahead) else first(
                    lookbehind + str
                ).skip(lookbehind.length, 0).followedBy(lookahead)
            }

            override fun toString(): String {
                return "first('$str')"
            }
        }
    }

    */
/** Returns a `Pattern` that matches the first occurrence of `character`.  *//*

    fun first(character: Char): SubPattern {
        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                val index = input.indexOf(character, fromIndex)
                return if (index >= 0) SubPatternMatch.backtrackable(1, input, index, 1) else null
            }

            override fun lookaround(lookbehind: String, lookahead: String): SubPattern {
                // first(lookbehind + char).skip(lookbehind) is more efficient with native String#indexOf().
                return if (lookbehind.isEmpty()) super.lookaround(lookbehind, lookahead) else first(
                    lookbehind + character
                ).skip(lookbehind.length, 0).followedBy(lookahead)
            }

            override fun toString(): String {
                return "first(\'$character\')"
            }
        }
    }

    */
/**
     * Returns a `Pattern` that matches the first character found by `charMatcher`.
     *
     * @since 6.0
     *//*

    fun first(charMatcher: CharPredicate): SubPattern {
        Objects.requireNonNull<Any>(charMatcher)
        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                for (i in fromIndex until input.length) {
                    if (charMatcher.test(input[i])) {
                        return SubPatternMatch.backtrackable(1, input, i, 1)
                    }
                }
                return null
            }

            override fun toString(): String {
                return "first($charMatcher)"
            }
        }
    }

    */
/**
     * Returns a `Pattern` that matches the last character found by `charMatcher`.
     *
     * @since 6.0
     *//*

    fun last(charMatcher: CharPredicate): SubPattern {
        return object : Last() {
            override fun match(input: String, fromIndex: Int, endIndex: Int): SubPatternMatch? {
                for (i in endIndex - 1 downTo fromIndex) {
                    if (charMatcher.test(input[i])) {
                        return SubPatternMatch.nonBacktrackable(input, i, 1)
                    }
                }
                return null
            }

            override fun toString(): String {
                return "last($charMatcher)"
            }
        }
    }

    */
/**
     * Returns a `Pattern` that matches the first occurrence of a word composed of `[a-zA-Z0-9_]` characters.
     *
     * @since 6.0
     *//*

    fun word(): SubPattern {
        return consecutive(CharPredicate.WORD)
    }

    */
/**
     * Returns a `Pattern` that matches the first occurrence of `word` that isn't
     * immediately preceded or followed by another "word" (`[a-zA-Z0-9_]`) character.
     *
     *
     * For example, if you are looking for an English word "cat" in the string "catchie has a cat",
     * `first("cat")` won't work because it'll match the first three letters of "cathie".
     * Instead, you should use `word("cat")` to skip over "cathie".
     *
     *
     * If your word boundary isn't equivalent to the regex `\W` character class, you can
     * define your own word boundary `CharMatcher` and then use [SubPattern.separatedBy]
     * instead. Say, if your word is lower-case alpha with dash ('-'), then:
     *
     * <pre>`CharMatcher boundary = CharMatcher.inRange('a', 'z').or(CharMatcher.is('-')).negate();
     * Substring.Pattern petFriendly = first("pet-friendly").separatedBy(boundary);
    `</pre> *
     *
     * @since 6.0
     *//*

    fun word(word: String): SubPattern {
        return first(word).separatedBy(CharPredicate.WORD.not())
    }

    */
/**
     * Returns a `Pattern` that matches from the beginning of the input string, a non-empty
     * sequence of leading characters identified by `matcher`.
     *
     *
     * For example: `leading(javaLetter()).from("System.err")` will result in `"System"`.
     *
     * @since 6.0
     *//*

    fun leading(matcher: CharPredicate): SubPattern {
        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                var len = 0
                var i = fromIndex
                while (i < input.length) {
                    if (!matcher.test(input[i])) {
                        break
                    }
                    i++
                    len++
                }
                return if (len == 0) null else SubPatternMatch.nonBacktrackable(
                    input,
                    fromIndex,
                    len
                )
            }

            override fun toString(): String {
                return "leading($matcher)"
            }
        }
    }

    */
/**
     * Returns a `Pattern` that matches from the end of the input string, a non-empty sequence
     * of trailing characters identified by `matcher`.
     *
     *
     * For example: `trailing(digit()).from("60612-3588")` will result in `"3588"`.
     *
     * @since 6.0
     *//*

    fun trailing(matcher: CharPredicate): SubPattern {
        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                var len = 0
                var i = input.length - 1
                while (i >= fromIndex) {
                    if (!matcher.test(input[i])) {
                        break
                    }
                    i--
                    len++
                }
                return if (len == 0) null else SubPatternMatch.suffix(input, len)
            }

            override fun toString(): String {
                return "trailing($matcher)"
            }
        }
    }

    */
/**
     * Returns a `Pattern` that matches the first non-empty sequence of consecutive characters
     * identified by `matcher`.
     *
     *
     * For example: `consecutive(javaLetter()).from("(System.out)")` will find `"System"`, and `consecutive(javaLetter()).repeatedly().from("(System.out)")` will produce
     * `["System", "out"]`.
     *
     *
     * Equivalent to `matcher.collapseFrom(string, replacement)`, you can do `consecutive(matcher).repeatedly().replaceAllFrom(string, replacement)`. But you can also do
     * things other than collapsing these consecutive groups, for example to inspect their values and
     * replace conditionally: `consecutive(matcher).repeatedly().replaceAllFrom(string, group ->
     * ...)`, or other more sophisticated use cases like building index maps of these sub sequences.
     *
     * @since 6.0
     *//*

    fun consecutive(matcher: CharPredicate): SubPattern {
        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                val end = input.length
                for (i in fromIndex until end) {
                    if (matcher.test(input[i])) {
                        var len = 1
                        var j = i + 1
                        while (j < end) {
                            if (!matcher.test(input[j])) {
                                break
                            }
                            j++
                            len++
                        }
                        return SubPatternMatch.backtrackable(len, input, i, len)
                    }
                }
                return null
            }

            override fun toString(): String {
                return "consecutive($matcher)"
            }
        }
    }

    */
/**
     * Returns a repeating pattern representing all the top-level groups from `regexPattern`.
     * If `regexPattern` has no capture group, the entire pattern is considered the only group.
     *
     *
     * For example, `topLevelGroups(compile("(g+)(o+)")).from("ggooo")` will return
     * `["gg", "ooo"]`.
     *
     *
     * Nested capture groups are not taken into account. For example: `topLevelGroups(compile("((foo)+(bar)*)(zoo)")).from("foofoobarzoo")` will return
     * `["foofoobar", "zoo"]`.
     *
     *
     * Note that the top-level groups are statically determined by the `regexPattern`.
     * Particularly, quantifiers on a capture group do not increase or decrease the number of captured
     * groups. That is, when matching `"(foo)+"` against `"foofoofoo"`, there will only
     * be one top-level group, with `"foo"` as the value.
     *
     * @since 5.3
     *//*

    */
/*fun topLevelGroups(regexPattern: java.util.regex.Pattern): RepeatingPattern {
        Objects.requireNonNull(regexPattern)
        return object : RepeatingPattern() {
            override fun match(string: String): Stream<SubPatternMatch> {
                val matcher = regexPattern.matcher(string)
                if (!matcher.find()) return Stream.empty()
                val groups = matcher.groupCount()
                return if (groups == 0) {
                    Stream.of(
                        SubPatternMatch.backtrackable(
                            1,
                            string,
                            matcher.start(),
                            matcher.end() - matcher.start()
                        )
                    )
                } else {
                    MoreStreams.whileNotNull(object : Supplier<SubPatternMatch?> {
                        private var next = 0
                        private var g = 1
                        override fun get(): SubPatternMatch? {
                            while (g <= groups) {
                                val start = matcher.start(g)
                                val end = matcher.end(g)
                                if (start >= next) {
                                    next = end
                                    return SubPatternMatch.backtrackable(1, string, start, end - start)
                                }
                                g++
                            }
                            return null
                        }
                    })
                }
            }

            override fun toString(): String {
                return "topLevelGroups($regexPattern)"
            }
        }
    }*//*

    */
/**
     * Returns a `Pattern` that matches the first occurrence of `regexPattern` and then
     * selects the capturing group identified by `group`.
     *
     *
     * For example, the following pattern finds the shard number (12) from a string like `12-of-99`:
     *
     * <pre>
     * import java.util.regex.Pattern;
     *
     * private static final Substring.Pattern SHARD_NUMBER =
     * Substring.first(Pattern.compile("(\\d+)-of-\\d+"), 1);
    </pre> *
     *
     * @throws IndexOutOfBoundsException if `group` is negative or exceeds the number of
     * capturing groups in `regexPattern`.
     *//*

    */
/**
     * Returns a `Pattern` that matches the first occurrence of `regexPattern`.
     *
     *
     * Unlike `str.replaceFirst(regexPattern, replacement)`,
     *
     * <pre>first(regexPattern).replaceFrom(str, replacement)</pre>
     *
     * treats the `replacement` as a literal string, with no special handling of backslash (\)
     * and dollar sign ($) characters.
     *//*

    fun first(regexPattern: Pattern, group: Int = 0): SubPattern {
        if (group < 0 || group > 0 && group > regexPattern.matcher("").groupCount()) {
            throw IndexOutOfBoundsException("Capturing group $group doesn't exist.")
        }
        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                val matcher = regexPattern.matcher(input)
                if (fromIndex <= input.length && matcher.find(fromIndex)) {
                    val start = matcher.start(group)
                    return SubPatternMatch.backtrackable(
                        1,
                        input,
                        start,
                        matcher.end(group) - start
                    )
                }
                return null
            }

            */
/** Delegate to native regex backtracking, which can be more efficient for regex patterns.  *//*

            override fun lookaround(lookbehind: String, lookahead: String): SubPattern {
                val builder = StringBuilder()
                if (!lookbehind.isEmpty()) {
                    builder.append("(?<=").append(java.util.regex.Pattern.quote(lookbehind))
                        .append(")")
                }
                builder.append("(").append(regexPattern).append(")")
                if (!lookahead.isEmpty()) {
                    builder.append("(?=").append(java.util.regex.Pattern.quote(lookahead))
                        .append(")")
                }
                return first(Pattern.compile(builder.toString()), group)
            }

            */
/** Delegate to native regex backtracking, which can be more efficient for regex patterns.  *//*

            override fun negativeLookaround(lookbehind: String, lookahead: String): SubPattern {
                if (lookahead.isEmpty()) { // negative lookbehind
                    return first(
                        Pattern.compile(
                            "(?<!" + Pattern.quote(
                                lookbehind
                            ) + ")" + regexPattern
                        )
                    )
                }
                return if (lookbehind.isEmpty()) { // negative lookahead
                    first(
                        Pattern.compile(
                            regexPattern.toString() + "(?!" + Pattern.quote(
                                lookahead
                            ) + ")"
                        )
                    )
                } else super.negativeLookaround(lookbehind, lookahead)
                // Regex has no negative front-and-back lookaround
            }

            override fun toString(): String {
                return "first(\"$regexPattern\", $group)"
            }
        }
    }

    */
/**
     * Returns a [Collector] that collects the input candidate [SubPattern] and reults in a
     * pattern that matches whichever that occurs first in the input string. For example you can use
     * it to find the first occurrence of any reserved word in a set:
     *
     * <pre>`Substring.Pattern reserved =
     * Stream.of("if", "else", "for", "public")
     * .map(Substring::word)
     * .collect(firstOccurrence());
    `</pre> *
     *
     * @since 6.1
     *//*

    */
/*fun firstOccurrence(): Collector<SubPattern, *, SubPattern> {
        class Occurrence(
            private val subPattern: SubPattern,
            val subPatternMatch: SubPatternMatch,
            private val stableOrder: Int
        ) {
            override fun toString(): String {
                return "$subPattern: $subPatternMatch"
            }

            fun enqueueNextOccurrence(input: String?, fromIndex: Int, queue: Queue<Occurrence>) {
                val nextMatch = subPattern.match(input, fromIndex)
                if (nextMatch != null) {
                    queue.add(Occurrence(subPattern, nextMatch, stableOrder))
                }
            }
        }

        val byIndex = Comparator.comparingInt { occurrence: Occurrence -> occurrence.subPatternMatch.index() }
            .thenComparingInt { occurrence: Occurrence -> occurrence.stableOrder }
        return Collectors.collectingAndThen(
            toImmutableList(),
            Function<R, RR> { candidates: R ->
                object : SubPattern() {
                    override fun match(input: String, fromIndex: Int): SubPatternMatch {
                        Objects.requireNonNull(input)
                        var best: SubPatternMatch? = null
                        for (candidate in candidates) {
                            val match = candidate.match(input, fromIndex) ?: continue
                            if (match.index() == fromIndex) { // First occurrence for sure.
                                return@collectingAndThen match
                            }
                            if (best == null || match.index() < best.index()) {
                                best = match
                            }
                        }
                        return@collectingAndThen best
                    }

                    override fun iterate(input: String): Stream<SubPatternMatch> {
                        val occurrences =
                            PriorityQueue(max(1, candidates.size()), byIndex)
                        for (i in 0 until candidates.size()) {
                            val candidate: SubPattern = candidates.get(i)
                            val match = candidate.match(input, 0)
                            if (match != null) {
                                occurrences.add(Occurrence(candidate, match, i))
                            }
                        }
                        return@collectingAndThen MoreStreams.whileNotNull {
                            val occurrence = occurrences.poll() ?: return@whileNotNull null
                            val match = occurrence.subPatternMatch

                            // For allOccurrencesOf([before(first('/')), first('/')]) against input = "foo/bar",
                            // before(first('/')) will match the first occurrence of "foo".
                            // In the next iteration, we want to start *after* the '/' for the repetition
                            // of before(first('/')), yet start from the '/' for the other unmatched first('/').
                            // The expected result is [foo, /].
                            if (match.repetitionStartIndex <= input.length) {
                                occurrence.enqueueNextOccurrence(
                                    input,
                                    match.repetitionStartIndex,
                                    occurrences
                                )
                            }
                            val waterMark = match.endIndex
                            while (true) {
                                val nextInLine = occurrences.peek()
                                if (nextInLine == null || nextInLine.subPatternMatch.index() >= waterMark) {
                                    return@whileNotNull match
                                }
                                occurrences.remove()
                                    .enqueueNextOccurrence(input, waterMark, occurrences)
                            }
                        }
                    }

                    // separatedBy() moves one char at a time when boundary mismatches.
                    // As such firstOccurrence().separatedBy().repeatedly() will end up re-applying all
                    // candidate patterns at every index.
                    //
                    // This override rewrites it to separatedBy().firstOccurrence().repeatedly(),
                    // Because firstOccurrence() implements the fast-forwarding optimization, the
                    // separatedBy() boundary scanning is significantly reduced.
                    //
                    // This rewrite is mostly equivalent before vs. after because if a boundary check
                    // disqualifies a candidate pattern returned by firstOccurrence(), all of the other
                    // candidate
                    // patterns will be tried.
                    //
                    // There is one subtle difference though. Without this override:
                    //     In ['foo', 'food'].collect(firstOccurrence()).separatedBy(whitespace());
                    //     'foo' will be matched and then separatedBy(whitespace()) will disqualify it;
                    //     The next iteration of separatedBy() will start from the second char 'o', so
                    //     'food' will never get a chance to match.
                    // With the override, the above expression is rewritten to:
                    //     ['foo', 'food'].separatedBy(whitespace()).collect(firstOccurrence()).
                    //     firstOccurrence().repeatedly() is in the driving seat and will attempt 'food'
                    //     from the first char.
                    override fun separatedBy(
                        boundaryBefore: CharPredicate,
                        boundaryAfter: CharPredicate
                    ): SubPattern {
                        Objects.requireNonNull<Any>(boundaryBefore)
                        Objects.requireNonNull<Any>(boundaryAfter)
                        return@collectingAndThen candidates.stream()
                            .map { c -> c.separatedBy(boundaryBefore, boundaryAfter) }
                            .collect(firstOccurrence())
                    }

                    override fun lookaround(
                        lookbehind: String,
                        lookahead: String
                    ): SubPattern {
                        return@collectingAndThen candidates.stream()
                            .map { c -> c.lookaround(lookbehind, lookahead) }
                            .collect(firstOccurrence())
                    }

                    override fun negativeLookaround(
                        lookbehind: String,
                        lookahead: String
                    ): SubPattern {
                        return@collectingAndThen candidates.stream()
                            .map { c -> c.negativeLookaround(lookbehind, lookahead) }
                            .collect(firstOccurrence())
                    }

                    override fun toString(): String {
                        return@collectingAndThen "firstOccurrenceOf($candidates)"
                    }
                }
            })
    }*//*


    */
/**
     * Returns a `Pattern` that matches the first occurrence of `stop1`, followed by an
     * occurrence of `stop2`, followed sequentially by occurrences of `moreStops` in
     * order, including any characters between consecutive stops.
     *
     *
     * Note that with more than two stops and if all the stops are literals, you may want to use
     * [StringFormat.span()][StringFormat.span] instead.
     *
     *
     * For example, to find hyperlinks like `<a href="...">...</a>`, you can use `StringFormat.span("<a href=\"{link}\">{...}</a>")`, which is equivalent to `spanningInOrder("<a href=\"", "\">", "</a>")` but more self-documenting with proper placeholder
     * names.
     *//*

    fun spanningInOrder(stop1: String, stop2: String, vararg moreStops: String): SubPattern {
        var result = first(stop1).extendTo(first(stop2))
        for (stop in moreStops) {
            result = result.extendTo(first(stop))
        }
        return result
    }

    */
/** Returns a `Pattern` that matches the last occurrence of `str`.  *//*

    fun last(str: String): SubPattern {
        return if (str.length == 1) {
            last(str[0])
        } else object : Last() {
            override fun match(input: String, fromIndex: Int, endIndex: Int): SubPatternMatch? {
                val index = if (str.isEmpty()) endIndex else input.lastIndexOf(str, endIndex - 1)
                return if (index >= fromIndex) SubPatternMatch.nonBacktrackable(
                    input,
                    index,
                    str.length
                ) else null
            }

            override fun toString(): String {
                return "last('$str')"
            }
        }
    }

    */
/** Returns a `Pattern` that matches the last occurrence of `character`.  *//*

    fun last(character: Char): SubPattern {
        return object : Last() {
            override fun match(input: String, fromIndex: Int, endIndex: Int): SubPatternMatch? {
                val index = input.lastIndexOf(character, endIndex - 1)
                return if (index >= fromIndex) SubPatternMatch.nonBacktrackable(
                    input,
                    index,
                    1
                ) else null
            }

            override fun toString(): String {
                return "last('$character')"
            }
        }
    }

    */
/**
     * Returns a `Pattern` that covers the substring before `delimiter`. For example:
     *
     * <pre>
     * String file = "/home/path/file.txt";
     * String path = Substring.before(last('/')).from(file).orElseThrow(...);
     * assertThat(path).isEqualTo("/home/path");
    </pre> *
     *//*

    fun before(delimiter: SubPattern): SubPattern {
        Objects.requireNonNull(delimiter)
        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                val match = delimiter.match(input, fromIndex)
                return if (match == null) null // For example when matching before(first("//")) against "http://", there should be
                // only one iteration, which is "http:". If the next scan starts before //, we'd get
                // an empty string match.
                //
                // For before(first('/')).separatedBy(), if boundary doesn't match, it's not loggically correct
                // to try the second '/'.
                else SubPatternMatch(
                    input,
                    fromIndex,
                    match.startIndex - fromIndex, Int.MAX_VALUE,
                    match.repetitionStartIndex
                )
            }

            override fun toString(): String {
                return "before($delimiter)"
            }
        }
    }

    */
/**
     * Returns a `Pattern` that covers the substring after `delimiter`. For example:
     *
     * <pre>
     * String file = "/home/path/file.txt";
     * String ext = Substring.after(last('.')).from(file).orElseThrow(...);
     * assertThat(ext).isEqualTo("txt");
    </pre> *
     *//*

    fun after(delimiter: SubPattern): SubPattern {
        Objects.requireNonNull(delimiter)
        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                val match = delimiter.match(input, fromIndex)
                return match?.following()
            }

            override fun toString(): String {
                return "after($delimiter)"
            }
        }
    }

    */
/**
     * Returns a `Pattern` that will match from the beginning of the original string up to the
     * substring matched by `pattern` *inclusively*. For example:
     *
     * <pre>
     * String uri = "http://google.com";
     * String schemeStripped = upToIncluding(first("://")).removeFrom(uri);
     * assertThat(schemeStripped).isEqualTo("google.com");
    </pre> *
     *
     *
     * To match from the start of `pattern` to the end of the original string, use [ ][SubPattern.toEnd] instead.
     *//*

    fun upToIncluding(subPattern: SubPattern): SubPattern {
        Objects.requireNonNull(subPattern)
        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                val match = subPattern.match(input, fromIndex)
                return if (match == null) null // Do not include the delimiter pattern in the next iteration.
                // upToIncluding(first('/')).separatedBy() should not backtrack to the second '/'.
                else SubPatternMatch(
                    input,
                    fromIndex,
                    match.endIndex - fromIndex, Int.MAX_VALUE,
                    match.repetitionStartIndex
                )
            }

            override fun toString(): String {
                return "upToIncluding($subPattern)"
            }
        }
    }

    */
/**
     * Returns a `Pattern` that will match the substring between the first `open` and the
     * first `close` after it.
     *
     *
     * If for example you need to find the substring between the first `"<-"` and the
     * *last* `"->"`, use `between(first("<-"), last("->"))` instead.
     *
     * @since 6.0
     *//*

    fun between(open: String, close: String): SubPattern {
        return between(first(open), first(close))
    }

    */
/**
     * Returns a `Pattern` that will match the substring between the first `open` and the
     * first `close` after it.
     *
     *
     * If for example you need to find the substring between the first and the *last* `'/'`, use `between(first('/'), last('/'))` instead.
     *
     * @since 6.0
     *//*

    fun between(open: Char, close: Char): SubPattern {
        return between(first(open), first(close))
    }

    */
/**
     * Returns a `Pattern` that will match the substring between `open` and `close`.
     * For example the following pattern finds the link text in markdown syntax:
     *
     * <pre>
     * private static final Substring.Pattern DEPOT_PATH =
     * Substring.between(first("//depot/"), last('/'));
     * assertThat(DEPOT_PATH.from("//depot/google3/foo/bar/baz.txt")).hasValue("google3/foo/bar");
    </pre> *
     *//*

    fun between(open: SubPattern, close: SubPattern): SubPattern {

        return object : SubPattern() {
            override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                val left = open.match(input, fromIndex) ?: return null
                val right = close.match(input, left.endIndex) ?: return null
                val startIndex = left.endIndex
                val len = right.startIndex - startIndex
                // Include the closing delimiter in the next iteration. This allows delimiters in
                // patterns like "/foo/bar/baz/" to be treated more intuitively.
                return SubPatternMatch.backtrackable( */
/*backtrackingOffset=*//*

                    left.backtrackIndex - startIndex,
                    input,
                    startIndex,  */
/*length=*//*

                    len
                )
            }

            override fun toString(): String {
                return "between($open, $close)"
            }
        }
    }

    private fun checkNumChars(maxChars: Int): Int {
        require(maxChars >= 0) { "Number of characters ($maxChars) cannot be negative." }
        return maxChars
    }

    */
/** A pattern that can be matched against a string, finding a single substring from it.  *//*

    abstract class SubPattern {
        */
/**
         * Matches this pattern against `string`, returning a `Match` if successful, or
         * `empty()` otherwise.
         *
         *
         * This is useful if you need to call [SubPatternMatch] methods, like [SubPatternMatch.remove] or
         * [SubPatternMatch.before]. If you just need the matched substring itself, prefer to use [ ][.from] instead.
         *//*

        fun `in`(string: String): Optional<SubPatternMatch> {
            return Optional.ofNullable(match(string))
        }

        */
/**
         * Matches this pattern against `string` starting from the character at `fromIndex`,
         * returning a `Match` if successful, or `empty()` otherwise.
         *
         *
         * Note that it treats `fromIndex` as the beginning of the string, so patterns like
         * [.prefix], [.BEGINNING] will attempt to match from this index.
         *
         * @throws IndexOutOfBoundsException if fromIndex is negative or greater than `string.length()`
         * @since 7.0
         *//*

        fun `in`(string: String, fromIndex: Int): Optional<SubPatternMatch> {
            if (fromIndex < 0) {
                throw IndexOutOfBoundsException("Invalid index ($fromIndex) < 0")
            }
            if (fromIndex > string.length) {
                throw IndexOutOfBoundsException(
                    "Invalid index (" + fromIndex + ") > length (" + string.length + ")"
                )
            }
            return Optional.ofNullable(match(string, fromIndex))
        }

        */
/**
         * Matches this pattern against `string`, returning the matched substring if successful,
         * or `empty()` otherwise. `pattern.from(str)` is equivalent to `pattern.in(str).map(Object::toString)`.
         *
         *
         * This is useful if you only need the matched substring itself. Use [.in] if you need
         * to call [SubPatternMatch] methods, like [SubPatternMatch.remove] or [SubPatternMatch.before].
         *//*

        fun from(string: CharSequence): Optional<String> {
            return Optional.ofNullable(Objects.toString(match(string.toString()), null))
        }

        */
/**
         * Matches this pattern against `string`, and returns a copy with the matched substring
         * removed if successful. Otherwise, returns `string` unchanged.
         *//*

        fun removeFrom(string: String): String {
            val match = match(string)
            return match?.remove() ?: string
        }

        */
/**
         * Returns a new string with the substring matched by `this` replaced by `replacement`. Returns `string` as-is if a substring is not found.
         *//*

        fun replaceFrom(string: String, replacement: CharSequence): String {
            return replaceFrom(
                string
            ) { m: SubPatternMatch? -> replacement }
        }

        */
/**
         * Returns a new string with the substring matched by `this` replaced by
         * the return value of `replacementFunction`.
         *
         *
         * For example, you can replace a single template placeholder using:
         *
         * <pre>`Substring.spanningInOrder("{", "}")
         * .replaceFrom(s, placeholder -> replacements.get(placeholder.skip(1, 1).toString()));
        `</pre> *
         *
         *
         * Returns `string` as-is if a substring is not found.
         *
         * @since 5.6
         *//*

        fun replaceFrom(
            string: String, replacementFunction: Function<in SubPatternMatch?, out CharSequence>
        ): String {
            val match = match(string)
            return match?.replaceWith(replacementFunction.apply(match)) ?: string
        }

        */
/**
         * Returns a `Pattern` that will match from the substring matched by `this` to the
         * end of the input string. For example:
         *
         * <pre>
         * String line = "return foo; // some comment...";
         * String commentRemoved = first("//").toEnd().removeFrom(line).trim();
         * assertThat(commentRemoved).isEqualTo("return foo;");
        </pre> *
         *
         *
         * To match from the beginning of the input string to the end of a pattern, use [ ][Substring.upToIncluding] instead.
         *//*

        fun toEnd(): SubPattern {
            val base = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    val match = base.match(input, fromIndex)
                    return match?.toEnd()
                }

                override fun toString(): String {
                    return "$base.toEnd()"
                }
            }
        }

        */
/**
         * Returns a `Pattern` that falls back to using `that` if `this` fails to
         * match.
         *//*

        fun or(that: SubPattern): SubPattern {
            Objects.requireNonNull(that)
            val base = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    val match = base.match(input, fromIndex)
                    return match ?: that.match(input, fromIndex)
                }

                // Allow separatedBy() to trigger backtracking.
                override fun separatedBy(
                    boundaryBefore: CharPredicate, boundaryAfter: CharPredicate
                ): SubPattern {
                    return base.separatedBy(boundaryBefore, boundaryAfter)
                        .or(that.separatedBy(boundaryBefore, boundaryAfter))
                }

                // Allow between() to trigger backtracking.
                override fun lookaround(lookbehind: String, lookahead: String): SubPattern {
                    return base.lookaround(lookbehind, lookahead)
                        .or(that.lookaround(lookbehind, lookahead))
                }

                // Allow notImmediatelyBetween() to trigger backtracking.
                override fun negativeLookaround(lookbehind: String, lookahead: String): SubPattern {
                    return base.negativeLookaround(lookbehind, lookahead)
                        .or(that.negativeLookaround(lookbehind, lookahead))
                }

                override fun peek(following: SubPattern): SubPattern {
                    return base.peek(following).or(that.peek(following))
                }

                override fun limit(maxChars: Int): SubPattern {
                    return base.limit(maxChars).or(that.limit(maxChars))
                }

                override fun skip(fromBeginning: Int, fromEnd: Int): SubPattern {
                    return base.skip(fromBeginning, fromEnd).or(that.skip(fromBeginning, fromEnd))
                }

                override fun toString(): String {
                    return "$base.or($that)"
                }
            }
        }

        */
/**
         * Returns a `Pattern` that's equivalent to this pattern except it only matches at
         * most `maxChars`.
         *
         * @since 6.1
         *//*

        open fun limit(maxChars: Int): SubPattern {
            checkNumChars(maxChars)
            val base = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    val m = base.match(input, fromIndex)
                    return m?.limit(maxChars)
                }

                // For, firstOccurrence().limit().repeatedly(), apply firstOccurrence().iterate()
                // and then apply limit() on the result matches to take advantage of the optimization.
                override fun iterate(input: String): Stream<SubPatternMatch> {
                    return base.iterate(input).map { m: SubPatternMatch ->
                        m.limit(
                            maxChars
                        )
                    }
                }

                override fun toString(): String {
                    return "$base.limit($maxChars)"
                }
            }
        }

        */
/**
         * Returns a `Pattern` that's equivalent to this pattern except it will skip up to `fromBeginnings` characters from the beginning of the match and up to `fromEnd` characters
         * from the end of the match.
         *
         *
         * If the match includes fewer characters, an empty match is returned.
         *
         * @since 6.1
         *//*

        open fun skip(fromBeginning: Int, fromEnd: Int): SubPattern {
            checkNumChars(fromBeginning)
            checkNumChars(fromEnd)
            val original = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    val m = original.match(input, fromIndex)
                    return m?.skip(fromBeginning, fromEnd)
                }

                // For firstOccurrence().skiip().repeatedly(), apply
                // firstOccurrence().iterate() to take advantage of the optimization and then apply
                // skip() on the result matches.
                override fun iterate(input: String): Stream<SubPatternMatch> {
                    return original.iterate(input).map { m: SubPatternMatch ->
                        m.skip(
                            fromBeginning,
                            fromEnd
                        )
                    }
                }

                override fun toString(): String {
                    return "$original.skip($fromBeginning, $fromEnd)"
                }
            }
        }

        */
/**
         * Similar to regex lookahead, returns a pattern that matches the `following`
         * pattern after it has matched this pattern. For example `first('/').then(first('/'))`
         * finds the second '/' character.
         *
         * @since 5.7
         *//*

        fun then(following: SubPattern): SubPattern {
            Objects.requireNonNull(following)
            val base = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    val preceding = base.match(input, fromIndex) ?: return null
                    val next = following.match(input, preceding.endIndex) ?: return null
                    // Keep the repetitionStartIndex strictly increasing to avoid the next iteration
                    // in repeatedly() to be stuck with no progress.
                    return if (next.repetitionStartIndex < preceding.repetitionStartIndex) SubPatternMatch(
                        input,
                        next.startIndex,
                        next.length,
                        preceding.backtrackIndex,
                        preceding.repetitionStartIndex
                    ) else next
                }

                override fun separatedBy(
                    boundaryBefore: CharPredicate,
                    boundaryAfter: CharPredicate
                ): SubPattern {
                    return base.then(following.separatedBy(boundaryBefore, boundaryAfter))
                }

                override fun lookaround(lookbehind: String, lookahead: String): SubPattern {
                    return base.then(following.lookaround(lookbehind, lookahead))
                }

                override fun negativeLookaround(lookbehind: String, lookahead: String): SubPattern {
                    return base.then(following.negativeLookaround(lookbehind, lookahead))
                }

                override fun toString(): String {
                    return "$base.then($following)"
                }
            }
        }



        */
/**
         * Return a `Pattern` equivalent to this `Pattern`, except it will fail to match
         * if the `following` pattern can't find a match in the substring after the current match.
         *
         *
         * Useful in asserting that the current match is followed by the expected pattern. For example:
         * `SCHEME_NAME.peek(prefix(':'))` returns the URI scheme name.
         *
         *
         * Note that unlike regex lookahead, no backtracking is attempted. So `first("foo").peek("bar")` will match "bafoobar" but won't match "foofoobar" because
         * the first "foo" isn't followed by "bar".
         *
         *
         * If look-ahead is needed, you can use [.followedBy] as in `first("foo").followedBy("bar")`.
         *
         *
         * If you are trying to define a boundary around or after your pattern similar to regex
         * anchor `'\b'`, consider using [.separatedBy] if the boundary can be detected by
         * a character.
         *
         * @since 6.0
         *//*

        open fun peek(following: SubPattern): SubPattern {
            Objects.requireNonNull(following)
            val base = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    val preceding = base.match(input, fromIndex) ?: return null
                    return if (following.match(
                            input,
                            preceding.endIndex
                        ) == null
                    ) null else preceding
                }

                override fun toString(): String {
                    return "$base.peek($following)"
                }
            }
        }



        */
/**
         * Returns an otherwise equivalent `Pattern`, except it only matches if it's next
         * to the beginning of the string, the end of the string, or the `separator` character(s).
         *
         *
         * Useful if you are trying to find a word with custom boundaries. To search for words
         * composed of regex `\w` character class, consider using [Substring.word] instead.
         *
         *
         * For lookahead and lookbehind assertions, consider using [.immediatelyBetween] or [ ][.followedBy] instead.
         *
         * @since 6.2
         *//*

        fun separatedBy(separator: CharPredicate): SubPattern {
            return separatedBy(separator, separator)
        }

        */
/**
         * Returns an otherwise equivalent `Pattern`, except it requires the
         * beginning of the match must either be the beginning of the string, or be separated from the rest
         * of the string by the `separatorBefore` character; and the end of the match must either
         * be the end of the string, or be separated from the rest of the string by the `separatorAfter` character.
         *
         *
         * Useful if you are trying to find a word with custom boundaries. To search for words
         * composed of regex `\w` character class, consider using [Substring.word] instead.
         *
         *
         * For lookahead and lookbehind assertions, consider using [.between] or [ ][.followedBy] instead.
         *
         * @since 6.2
         *//*

        open fun separatedBy(separatorBefore: CharPredicate, separatorAfter: CharPredicate): SubPattern {
            Objects.requireNonNull<Any>(separatorBefore)
            Objects.requireNonNull<Any>(separatorAfter)
            val target = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    var fromIndex = fromIndex
                    while (fromIndex <= input.length) {
                        if (fromIndex > 0 && !separatorBefore.test(input[fromIndex - 1])) {
                            fromIndex++
                            continue  // The current position cannot possibly be the beginning of match.
                        }
                        val match = target.match(input, fromIndex) ?: return null
                        if (match.startIndex == fromIndex // Already checked boundaryBefore
                            || separatorBefore.test(input[match.startIndex - 1])
                        ) {
                            val boundaryIndex = match.endIndex
                            if (boundaryIndex >= input.length
                                || separatorAfter.test(input[boundaryIndex])
                            ) {
                                return match
                            }
                        }
                        fromIndex = match.backtrackFrom(fromIndex)
                    }
                    return null
                }

                override fun toString(): String {
                    return "$target.separatedBy($separatorBefore, $separatorAfter)"
                }
            }
        }

        */
/**
         * Returns an otherwise equivalent pattern except it requires the matched substring be
         * immediately preceded by the `lookbehind` string and immediately followed by the `after` string.
         *
         *
         * Similar to regex lookarounds, the returned pattern will backtrack until the lookaround is
         * satisfied. That is, `word().immediatelyBetween("(", ")")` will find the "bar" substring inside the
         * parenthesis from "foo (bar)".
         *
         *
         * If you need lookahead only, use [.followedBy] instead; for lookbehind only, pass an
         * empty string as the `lookahead` string, as in: `word().immediatelyBetween(":", "")`.
         *
         * @since 6.2
         *//*

        fun immediatelyBetween(lookbehind: String, lookahead: String): SubPattern {
            Objects.requireNonNull(lookbehind)
            Objects.requireNonNull(lookahead)
            return if (lookbehind.isEmpty() && lookahead.isEmpty()) this else lookaround(
                lookbehind,
                lookahead
            )
        }

        */
/**
         * Similar to [.immediatelyBetween], but allows including the `lookbehind` and/or `lookahead` inclusive in the match.
         *
         *
         * For example, to split around all "{placholder_name}", you can use:
         *
         * <pre>`PLACEHOLDER_NAME_PATTERN.immediatelyBetween("{", INCLUSIVE, "}", INCLUSIVE)
         * .split(input);
        `</pre> *
         *
         * @since 7.0
         *//*

        fun immediatelyBetween(
            lookbehind: String,
            lookbehindBound: BoundStyle,
            lookahead: String,
            lookaheadBound: BoundStyle
        ): SubPattern {
            val withLookaround = lookaround(lookbehind, lookahead)
            val behind =
                if (Objects.requireNonNull(lookbehindBound) == BoundStyle.INCLUSIVE) lookbehind.length else 0
            val ahead =
                if (Objects.requireNonNull(lookaheadBound) == BoundStyle.INCLUSIVE) lookahead.length else 0
            if (behind == 0 && ahead == 0) {
                return withLookaround
            }
            val original = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    val match = withLookaround.match(input, fromIndex)
                    return match?.expand(behind, ahead)
                }

                override fun toString(): String {
                    return (original
                        .toString() + ".immediatelyBetween('"
                            + lookbehind
                            + "', "
                            + lookbehindBound
                            + ", '"
                            + lookahead
                            + "', "
                            + lookaheadBound
                            + ")")
                }
            }
        }

        */
/**
         * Returns an otherwise equivalent pattern except it requires the matched substring *not*
         * be immediately preceded by the `lookbehind` string and immediately followed by the `after` string.
         *
         *
         * Similar to regex negative lookarounds, the returned pattern will backtrack until the
         * negative lookaround is satisfied. That is, `word().notImmediatelyBetween("(", ")")` will find the
         * "bar" substring from "(foo) bar".
         *
         *
         * If you need negative lookahead only, use [.notFollowedBy] instead; for negative
         * lookbehind only, pass an empty string as the `lookahead` string, as in: `word().notImmediatelyBetween(":", "")`.
         *
         *
         * If the pattern shouldn't be preceded or followed by particular character(s), consider
         * using [.separatedBy]. The following code finds "911" but only if it's at the beginning
         * of a number:
         *
         * <pre>`Substring.Pattern emergency =
         * first("911").separatedBy(CharPredicate.range('0', '9').not(), CharPredicate.ANY);
        `</pre> *
         *
         * @since 6.2
         *//*

        fun notImmediatelyBetween(lookbehind: String, lookahead: String): SubPattern {
            Objects.requireNonNull(lookbehind)
            Objects.requireNonNull(lookahead)
            return if (lookbehind.isEmpty() && lookahead.isEmpty()) NONE else negativeLookaround(
                lookbehind,
                lookahead
            )
        }

        */
/**
         * Returns an otherwise equivalent pattern except it requires the matched substring be
         * immediately followed by the `lookahead` string.
         *
         *
         * Similar to regex negative lookahead, the returned pattern will backtrack until the lookahead is
         * satisfied. That is, `word().followedBy(":")` will find the "Joe" substring from "To
         * Joe:".
         *
         *
         * If you need lookbehind, or both lookahead and lookbehind, use [.immediatelyBetween] instead.
         *
         * @since 6.2
         *//*

        fun followedBy(lookahead: String): SubPattern {
            return immediatelyBetween("", lookahead)
        }

        */
/**
         * Returns an otherwise equivalent pattern except it requires the matched substring *not*
         * be immediately followed by the `lookahead` string.
         *
         *
         * Similar to regex negative lookahead, the returned pattern will backtrack until the
         * negative lookahead is satisfied. That is, `word().notFollowedBy(" ")` will find the
         * "Joe" substring from "To Joe:".
         *
         *
         * If you need negative lookbehind, or both negative lookahead and lookbehind, use [ ][.notImmediatelyBetween] instead.
         *
         *
         * If the pattern shouldn't be followed by particular character(s), consider using [ ][.separatedBy]. The following code finds the file extension name ".java" if it's not followed
         * by another letter:
         *
         * <pre>`CharPredicate letter = Character::isJavaIdentifierStart;
         * Substring.Pattern javaExtension =
         * first(".java").separatedBy(CharPredicate.ANY, letter.not());
        `</pre> *
         *
         * @since 6.2
         *//*

        fun notFollowedBy(lookahead: String): SubPattern {
            return notImmediatelyBetween("", lookahead)
        }

        */
/**
         * Returns an otherwise equivalent pattern except it requires the matched substring be
         * immediately preceded by the `lookahead` string.
         *
         *
         * Similar to regex lookbehind, the returned pattern will backtrack until the lookbehind is
         * satisfied. That is, `word().precededBy(": ")` will find the "Please" substring from
         * "Amy: Please come in".
         *
         * @since 6.2
         *//*

        fun precededBy(lookbehind: String): SubPattern {
            return immediatelyBetween(lookbehind, "")
        }

        */
/**
         * Returns an otherwise equivalent pattern except it requires the matched substring *not* be
         * immediately preceded by the `lookbehind` string.
         *
         *
         * Similar to regex negative lookbehind, the returned pattern will backtrack until the
         * negative lookbehind is satisfied. For example, `word().notPrecededBy("(")` will find the
         * "bar" substring from "(foo+bar)".
         *
         * @since 6.2
         *//*

        fun notPrecededBy(lookbehind: String): SubPattern {
            return notImmediatelyBetween(lookbehind, "")
        }



        */
/**
         * Matches this pattern and then matches `following`.
         * The result matches from the beginning of this pattern to the end of `following`.
         *//*

        fun extendTo(following: SubPattern): SubPattern {
            Objects.requireNonNull(following)
            val base = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    val preceding = base.match(input, fromIndex) ?: return null
                    val next = following.match(input, preceding.endIndex) ?: return null
                    return SubPatternMatch(
                        input,
                        preceding.startIndex,
                        next.endIndex - preceding.startIndex,
                        preceding.backtrackIndex,  // Keep the repetitionStartIndex strictly increasing to avoid the next iteration
                        // in repeatedly() to be stuck with no progress.
                        Math.max(preceding.repetitionStartIndex, next.repetitionStartIndex)
                    )
                }

                override fun toString(): String {
                    return "$base.extendTo($following)"
                }
            }
        }

        */
/**
         * Splits `string` into two parts that are separated by this separator pattern. For
         * example:
         *
         * <pre>`Optional<KeyValue> keyValue = first('=').split("name=joe").join(KeyValue::new);
        `</pre> *
         *
         *
         * If you need to trim the key-value pairs, use [.splitThenTrim].
         *
         *
         * To split a string into multiple substrings delimited by a delimiter, use [.repeatedly].
         *
         * @since 5.0
         *//*

        fun split(string: CharSequence): BiOptional<String, String> {
            val match = match(string.toString())
            return if (match == null) BiOptional.empty() else BiOptional.of(
                match.before(),
                match.after()
            )
        }

        */
/**
         * Splits `string` into two parts that are separated by this separator pattern, with
         * leading and trailing whitespaces trimmed. For example:
         *
         * <pre>`Optional<KeyValue> keyValue = first('=').splitThenTrim("name = joe ").join(KeyValue::new);
        `</pre> *
         *
         *
         * If you are trying to parse a string to a key-value data structure (`Map`, `Multimap` etc.), you can use `com.google.common.base.Splitter.MapSplitter` though it's
         * limited to `Map` and doesn't allow duplicate keys:
         *
         * <pre>`String toSplit = " x -> y, z-> a ";
         * Map<String, String> result = Splitter.on(',')
         * .trimResults()
         * .withKeyValueSeparator(Splitter.on("->"))
         * .split(toSplit);
        `</pre> *
         *
         * Alternatively, you can use `Substring` to allow duplicate keys and to split into
         * multimaps or other types:
         *
         * <pre>`import static com.google.mu.util.stream.MoreCollectors.mapping;
         *
         * String toSplit = " x -> y, z-> a, x -> t ";
         * ImmutableListMultimap<String, String> result = first(',')
         * .repeatedly()
         * .split(toSplit)
         * .map(first("->")::splitThenTrim)
         * .collect(
         * mapping(
         * kv -> kv.orElseThrow(...),
         * ImmutableListMultimap::toImmutableListMultimap));
        `</pre> *
         *
         *
         * To split a string into multiple substrings delimited by a delimiter, use [.repeatedly].
         *
         * @since 5.0
         *//*

        fun splitThenTrim(string: CharSequence): BiOptional<String, String> {
            val match = match(string.toString())
            return if (match == null) BiOptional.empty() else BiOptional.of(
                match.before().trim { it <= ' ' }, match.after().trim { it <= ' ' })
        }

        */
/**
         * Returns a [RepeatingPattern] that applies this pattern repeatedly against the input
         * string. That is, after each iteration, the pattern is applied again over the substring after
         * the match, repeatedly until no match is found.
         *
         * @since 5.2
         *//*

        fun repeatedly(): RepeatingPattern {
            return object : RepeatingPattern() {
                override fun match(input: String): Stream<SubPatternMatch> {
                    return iterate(Objects.requireNonNull(input))
                }

                override fun toString(): String {
                    return this@SubPattern.toString() + ".repeatedly()"
                }
            }
        }

        */
/**
         * Matches against `string` starting from `fromIndex`, and returns null if not
         * found.
         *//*

        abstract fun match(string: String, fromIndex: Int): SubPatternMatch?

        */
/** Applies this pattern repeatedly against `input` and returns all iterations.  *//*

        open fun iterate(input: String): Stream<SubPatternMatch> {
            return whileNotNull(
                object : Supplier<SubPatternMatch?> {
                    private val end = input.length
                    private var nextIndex = 0
                    override fun get(): SubPatternMatch? {
                        if (nextIndex > end) {
                            return null
                        }
                        val match = match(input, nextIndex) ?: return null
                        nextIndex =
                            if (match.endIndex == end) { // We've consumed the entire string.
                                Int.MAX_VALUE
                            } else if (match.repetitionStartIndex > nextIndex) {
                                match.repetitionStartIndex
                            } else {
                                throw IllegalStateException(
                                    "Infinite loop detected at " + match.repetitionStartIndex
                                )
                            }
                        return match
                    }
                })
        }

        private fun match(string: String): SubPatternMatch? {
            return match(string, 0)
        }

        open fun lookaround(lookbehind: String, lookahead: String): SubPattern {
            val target = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    var fromIndex = fromIndex
                    val lastIndex = input.length - lookahead.length
                    while (fromIndex <= lastIndex) {
                        val match = target.match(input, fromIndex)
                        if (match == null || match.isImmediatelyBetween(lookbehind, lookahead)) {
                            return match
                        }
                        fromIndex = match.backtrackFrom(fromIndex)
                    }
                    return null
                }

                override fun toString(): String {
                    return "$target.immediatelyBetween('$lookbehind', '$lookahead')"
                }
            }
        }

        open fun negativeLookaround(lookbehind: String, lookahead: String): SubPattern {
            val target = this
            return object : SubPattern() {
                override fun match(input: String, fromIndex: Int): SubPatternMatch? {
                    var fromIndex = fromIndex
                    while (fromIndex <= input.length) {
                        val match = target.match(input, fromIndex)
                        if (match == null || !match.isImmediatelyBetween(lookbehind, lookahead)) {
                            return match
                        }
                        fromIndex = match.backtrackFrom(fromIndex)
                    }
                    return null
                }

                override fun toString(): String {
                    return "$target.notImmediatelyBetween('$lookbehind', '$lookahead')"
                }
            }
        }

        */
/**
         * Do not depend on the string representation of Substring, except for subtypes [Prefix]
         * and [Suffix] that have an explicitly defined representation.
         *//*

        override fun toString(): String {
            return super.toString()
        }
    }

    */
/**
     * A substring pattern to be applied repeatedly on the input string, each time over the remaining
     * substring after the previous match.
     *
     * @since 5.2
     *//*

    abstract class RepeatingPattern() {
        */
/**
         * Applies this pattern against `string` and returns a stream of each iteration.
         *
         *
         * Iterations happen in strict character encounter order, from the beginning of the input
         * string to the end, with no overlapping. When a match is found, the next iteration is
         * guaranteed to be in the substring after the current match. For example, `between(first('/'), first('/')).repeatedly().match("/foo/bar/baz/")` will return `["foo", "bar", "baz"]`. On the other hand, `after(last('/')).repeatedly().match("/foo/bar")` will only return "bar".
         *
         *
         * Pattern matching is lazy and doesn't start until the returned stream is consumed.
         *
         *
         * An empty stream is returned if this pattern has no matches in the `input` string.
         *//*

        abstract fun match(input: String): Stream<SubPatternMatch>

        */
/**
         * Applies this pattern against `string` and returns a stream of each iteration.
         *
         *
         * Iterations happen in strict character encounter order, from the beginning of the input
         * string to the end, with no overlapping. When a match is found, the next iteration is
         * guaranteed to be in the substring after the current match. For example, `between(first('/'), first('/')).repeatedly().from("/foo/bar/baz/")` will return `["foo", "bar", "baz"]`. On the other hand, `after(last('/')).repeatedly().from("/foo/bar")` will only return "bar".
         *
         *
         * Pattern matching is lazy and doesn't start until the returned stream is consumed.
         *
         *
         * An empty stream is returned if this pattern has no matches in the `input` string.
         *//*

        fun from(input: CharSequence): Stream<String> {
            return match(input.toString()).map { obj: SubPatternMatch -> obj.toString() }
        }

        */
/**
         * Returns a new string with all [matches][.match] of this pattern removed. Returns `string` as is if no match is found.
         *//*

        fun removeAllFrom(string: String): String {
            return replaceAllFrom(
                string
            ) { m: SubPatternMatch? -> "" }
        }

        */
/**
         * Returns a new string with all [matches][.match] of this pattern replaced by applying
         * `replacementFunction` for each match.
         *
         *
         * `replacementFunction` must not return null. Returns `string` as-is if no match
         * is found.
         *//*

        fun replaceAllFrom(
            string: String, replacementFunction: Function<in SubPatternMatch?, out CharSequence>
        ): String {
            val matches = match(string).iterator()
            if (!matches.hasNext()) {
                return string
            }
            // Add the chars between the previous and current match.
            val builder = StringBuilder(string.length)
            var index = 0
            do {
                val match = matches.next()
                val replacement = replacementFunction.apply(match)
                    ?: throw NullPointerException("No replacement is returned for $match")
                builder
                    .append(string, index, match.startIndex)
                    .append(replacement)
                index = match.endIndex
            } while (matches.hasNext())

            // Add the remaining chars
            return builder.append(string, index, string.length).toString()
        }

        */
/**
         * Returns a stream of `Match` objects delimited by every match of this pattern. If this
         * pattern isn't found in `string`, the full string is matched.
         *
         *
         * The returned `Match` objects are cheap "views" of the matched substring sequences.
         * Because `Match` implements `CharSequence`, the returned `Match` objects can
         * be directly passed to `CharSequence`-accepting APIs such as `com.google.common.base.CharMatcher.trimFrom()` and [SubPattern.splitThenTrim] etc.
         *//*

        fun split(string: String): Stream<SubPatternMatch> {
            return whileNotNull(
                object : Supplier<SubPatternMatch?> {
                    var next = 0
                    var it = match(string).iterator()
                    override fun get(): SubPatternMatch? {
                        if (it.hasNext()) {
                            val delim = it.next()
                            val result = SubPatternMatch.nonBacktrackable(string, next, delim.index() - next)
                            next = delim.endIndex
                            return result
                        }
                        return if (next >= 0) {
                            val result = SubPatternMatch.nonBacktrackable(string, next, string.length - next)
                            next = -1
                            result
                        } else {
                            null
                        }
                    }
                })
        }

        */
/**
         * Returns a stream of `Match` objects delimited by every match of this pattern. with
         * whitespaces trimmed.
         *
         *
         * The returned `Match` objects are cheap "views" of the matched substring sequences.
         * Because `Match` implements `CharSequence`, the returned `Match` objects can
         * be directly passed to `CharSequence`-accepting APIs such as `com.google.common.base.CharMatcher.trimFrom()` and [SubPattern.split] etc.
         *//*

        fun splitThenTrim(string: String): Stream<SubPatternMatch> {
            return split(string).map { obj: SubPatternMatch -> obj.trim() }
        }

        */
/**
         * Returns a stream of `Match` objects from the input `string` as demarcated by this
         * delimiter pattern. It's similar to [.split] but includes both the substrings split by
         * the delimiters and the delimiter substrings themselves, interpolated in the order they appear
         * in the input string.
         *
         *
         * For example,
         *
         * <pre>`spanningInOrder("{", "}").repeatedly().cut("Dear {user}: please {act}.")
        `</pre> *
         *
         * will result in the stream of `["Dear ", "{user}", ": please ", "{act}", "."]`.
         *
         *
         * The returned `Match` objects are cheap "views" of the matched substring sequences.
         * Because `Match` implements `CharSequence`, the returned `Match` objects can
         * be directly passed to `CharSequence`-accepting APIs such as [ ][CharMatcher.trimFrom], [SubPattern.splitThenTrim], etc.
         *
         * @since 7.1
         *//*

        fun cut(string: String): Stream<SubPatternMatch> {
            val delimiters = match(string).iterator()
            return whileNotNull(
                object : Supplier<SubPatternMatch?> {
                    var delimiter: SubPatternMatch? = null
                    var next = 0
                    override fun get(): SubPatternMatch? {
                        if (next == -1) {
                            return null
                        }
                        if (delimiter == null) { // Should return the substring before the next delimiter.
                            return if (delimiters.hasNext()) {
                                delimiter = delimiters.next()
                                val result = SubPatternMatch.nonBacktrackable(string, next, delimiter!!.index() - next)
                                next = delimiter!!.endIndex
                                result
                            } else {
                                val result = SubPatternMatch.nonBacktrackable(string, next, string.length - next)
                                next = -1
                                result
                            }
                        }
                        // should return delimiter
                        val result: SubPatternMatch = delimiter!!
                        delimiter = null
                        return result
                    }
                })
        }

        */
/**
         * Returns a [BiStream] of key value pairs from `input`.
         *
         *
         * The key-value pairs are delimited by this repeating pattern.
         * with the key and value separated by `keyValueSeparator`.
         *
         *
         * Empty parts (including leading and trailing separator) are ignored.
         * Although whitespaces are not trimmed. For example:
         *
         * <pre>`first(',')
         * .repeatedly()
         * .splitKeyValuesAround(first('='), "k1=v1,,k2=v2,")
        `</pre> *
         * will result in a `BiStream` equivalent to `[(k1, v1), (k2, v2)]`,
         * but `"k1=v1, ,k2=v2"` will fail to be split due to the whitespace after the first
         * `','`.
         *
         *
         * Non-empty parts where `keyValueSeparator` is absent will result in
         * [IllegalArgumentException].
         *
         *
         * For alternative splitting strategies, like, if you want to reject instead of ignoring
         * empty parts. consider to use [.split] and [SubPattern.split] directly,
         * such as:
         *
         * <pre>`first(',')
         * .repeatedly()
         * .split("k1=v1,,k2=v2,")  // the redundant ',' will throw IAE
         * .collect(
         * GuavaCollectors.toImmutableMap(
         * m -> first('=').split(m).orElseThrow(...)));
        `</pre> *
         *
         * Or, if you want to ignore unparsable parts:
         *
         * <pre>`first(',')
         * .repeatedly()
         * .split("k1=v1,k2>v2")  // Ignore the unknown "k2>v2"
         * .map(first('=')::split)
         * .collect(
         * MoreCollectors.flatMapping(
         * BiOptional::stream,
         * toImmutableMap()));
        `</pre> *
         *
         * @since 5.9
         *//*

        */
/*fun splitKeyValuesAround(
            keyValueSeparator: SubPattern, input: String
        ): BiStream<String, String> {
            return BiStream.from(
                split(input)
                    .filter { m: SubPatternMatch -> m.length > 0 }
                    .map(Function<SubPatternMatch, R> { m: SubPatternMatch ->
                        keyValueSeparator
                            .split(m)
                            .orElseThrow { IllegalArgumentException("Cannot split key values from '$m'") }
                    })
            )
        }*//*


        */
/**
         * Returns a [BiStream] of key value pairs from `input`.
         *
         *
         * The key-value pairs are delimited by this repeating pattern.
         * with the key and value separated by `keyValueSeparator`.
         *
         *
         * All keys and values are trimmed, with empty parts (including leading and trailing
         * separator) ignored. For example:
         *
         * <pre>`first(',')
         * .repeatedly()
         * .splitThenTrimKeyValuesAround(first('='), "k1 = v1, , k2=v2,")
        `</pre> *
         * will result in a `BiStream` equivalent to `[(k1, v1), (k2, v2)]`.
         *
         *
         * Non-empty parts where `keyValueSeparator` is absent will result in
         * [IllegalArgumentException].
         *
         *
         * For alternative splitting strategies, like, if you want to reject instead of ignoring
         * empty parts. consider to use [.split] and [SubPattern.splitThenTrim] directly,
         * such as:
         *
         * <pre>`first(',')
         * .repeatedly()
         * .split("k1 = v1, , k2=v2,")  // the redundant ',' will throw IAE
         * .collect(
         * GuavaCollectors.toImmutableMap(
         * m -> first('=').splitThenTrim(m).orElseThrow(...)));
        `</pre> *
         *
         * Or, if you want to ignore unparsable parts:
         *
         * <pre>`first(',')
         * .repeatedly()
         * .split("k1 = v1, k2 > v2")  // Ignore the unknown "k2 > v2"
         * .map(first('=')::splitThenTrim)
         * .collect(
         * MoreCollectors.flatMapping(
         * BiOptional::stream,
         * toImmutableMap()));
        `</pre> *
         *
         * @since 5.9
         *//*

       */
/* fun splitThenTrimKeyValuesAround(
            keyValueSeparator: SubPattern, input: String
        ): BiStream<String, String> {
            return BiStream.from(
                splitThenTrim(input)
                    .filter { m: SubPatternMatch -> m.length > 0 }
                    .map(Function<SubPatternMatch, R> { m: SubPatternMatch ->
                        keyValueSeparator
                            .splitThenTrim(m)
                            .orElseThrow { IllegalArgumentException("Cannot split key values from '$m'") }
                    })
            )
        }*//*


        fun splitThenTrimKeyValuesAround(
            keyValueSeparator: SubPattern, input: String
        ): List<Both<String, String>> {
            return splitThenTrim(input)
                .filter { m: SubPatternMatch -> m.isNotEmpty() }
                .map { m: SubPatternMatch ->
                    keyValueSeparator
                        .splitThenTrim(m)
                        .orElseThrow { IllegalArgumentException("Cannot split key values from '$m'") }
                }.toList()
        }

        */
/**
         * Returns the alternation of this pattern from the `input` string, with the matched
         * substring alternated with the trailing substring before the next match.
         *
         *
         * For example: to find bulleted items (strings prefixed by `1:`, `2:`,
         * `456:` etc.), you can:
         *
         * <pre>`Substring.Pattern bulletNumber = consecutive(CharPredicate.range('0', '9'))
         * .separatedBy(CharPredicate.WORD.not(), CharPredicate.is(':'));
         * Map<Integer, String> bulleted = bulletNumber.repeatedly()
         * .alternationFrom("1: go home;2: feed 2 cats 3: sleep tight.")
         * .mapKeys(n -> Integer.parseInt(n))
         * .mapValues(withColon -> prefix(":").removeFrom(withColon.toString()).trim())
         * .toMap();
         * // => [{1, "go home;"}, {2, "feed 2 cats"}, {3, "sleep tight."}]
        `</pre> *
         *
         * @since 6.1
         *//*

        */
/*fun alternationFrom(input: String): BiStream<String, String> {
            return Stream.concat(match(input), Stream.of(END.`in`(input).get()))
                .collect(BiStream.toAdjacentPairs())
                .mapValues { k, k2 -> input.substring(k.index() + k.length(), k2.index()) }
                .mapKeys(SubPatternMatch::toString)
        }*//*

    }

    */
/**
     * An immutable string prefix `Pattern` with extra utilities such as [ ][.addToIfAbsent], [.removeFrom], [.isIn] etc.
     *
     *
     * Can usually be declared as a constant to save allocation cost. Because `Prefix`
     * implements [CharSequence], it can be used almost interchangeably as a string. You can:
     *
     *
     *  * directly prepend a prefix as in `HOME_PREFIX + path`;
     *  * or prepend it into a `StringBuilder`: `builder.insert(0, HOME_PREFIX)`;
     *  * pass it to any CharSequence-accepting APIs such as `CharMatcher.anyOf(...).matchesAnyOf(MY_PREFIX)`, `Substring.first(':').splitThenTrim(MY_PREFIX)` etc.
     *
     *
     * @since 4.6
     *//*

    class Prefix(private val prefix: String) : SubPattern(), CharSequence {
        */
/**
         * Returns true if `source` starts with this prefix.
         *
         * @since 5.7
         *//*

        fun isIn(source: CharSequence): Boolean {
            if (source is String) {
                return source.startsWith(prefix)
            }
            val prefixChars = prefix.length
            val existingChars = source.length
            if (existingChars < prefixChars) {
                return false
            }
            for (i in 0 until prefixChars) {
                if (prefix[i] != source[i]) {
                    return false
                }
            }
            return true
        }

        */
/**
         * If `string` has this prefix, return it as-is; otherwise, return it with this prefix
         * prepended.
         *
         * @since 4.8
         *//*

        fun addToIfAbsent(string: String): String {
            return if (string.startsWith(prefix)) string else prefix + string
        }

        */
/**
         * If `builder` does not already have this prefix, prepend this prefix to it.
         *
         * @return true if this prefix is prepended
         * @since 5.7
         *//*

        fun addToIfAbsent(builder: StringBuilder): Boolean {
            val shouldAdd = !isIn(builder)
            if (shouldAdd) {
                builder.insert(0, prefix)
            }
            return shouldAdd
        }

        */
/**
         * Returns a *view* of `source` with this prefix hidden away if present, or else
         * returns `source` as is.
         *
         * @since 6.5
         *//*

        fun hideFrom(source: String): CharSequence {
            */
/*if (isEmpty()) {
                return Objects.requireNonNull(source)
            }*//*

            val match = match(source, 0)
            return match?.following() ?: source
        }

        */
/**
         * Removes this prefix from `builder` if it starts with the prefix.
         *
         * @return true if this prefix is removed
         * @since 5.7
         *//*

        fun removeFrom(builder: StringBuilder): Boolean {
            val present = isIn(builder)
            if (present) {
                builder.deleteRange(0, length)
            }
            return present
        }

        */
/**
         * Replaces this prefix from `builder` with `replacement` if it starts with the
         * prefix.
         *
         * @return true if this prefix is replaced
         * @since 5.7
         *//*

        fun replaceFrom(builder: StringBuilder, replacement: CharSequence): Boolean {
            Objects.requireNonNull(replacement)
            val present = isIn(builder)
            if (present) {
                builder.replace(0, length, replacement.toString())
            }
            return present
        }

        */
/** @since 5.7
         *//*

        override fun get(index: Int): Char {
            return prefix[index]
        }

        */
/** @since 5.7
         *//*

        override fun subSequence(start: Int, end: Int): String {
            return prefix.substring(start, end)
        }

        */
/**
         * Returns the length of this prefix.
         *
         * @since 5.7
         *//*

        */
/*override fun length(): Int {
            return prefix.length
        }*//*




        override fun hashCode(): Int {
            return prefix.hashCode()
        }

        override val length: Int
            get() = prefix.length

        override fun equals(obj: Any?): Boolean {
            return obj is Prefix && prefix == obj.prefix
        }

        */
/** Returns this prefix string.  *//*

        override fun toString(): String {
            return prefix
        }

        override fun match(input: String, fromIndex: Int): SubPatternMatch? {
            return if (input.startsWith(prefix, fromIndex)) SubPatternMatch.nonBacktrackable(
                input,
                fromIndex,
                prefix.length
            ) else null
        }
    }

    */
/**
     * An immutable string suffix `Pattern` with extra utilities such as [ ][.addToIfAbsent], [.removeFrom], [.isIn] etc.
     *
     *
     * Can usually be declared as a constant to save allocation cost. Because `Suffix`
     * implements [CharSequence], it can be used almost interchangeably as a string. You can:
     *
     *
     *  * directly append a suffix as in `path + SHARD_SUFFIX`;
     *  * or append the suffix into a `StringBuilder`: `builder.append(SHARD_SUFFIX)`};
     *  * pass it to any CharSequence-accepting APIs such as `CharMatcher.anyOf(...).matchesAnyOf(MY_PREFIX)`, `Substring.first(':').splitThenTrim(MY_PREFIX)` etc.
     *
     *
     * @since 4.6
     *//*

    class Suffix(private val suffix: String) : SubPattern(), CharSequence {
        */
/**
         * Returns true if `source` ends with this suffix.
         *
         * @since 5.7
         *//*

        fun isIn(source: CharSequence): Boolean {
            if (source is String) {
                return source.endsWith(suffix)
            }
            val suffixChars = suffix.length
            val existingChars = source.length
            if (existingChars < suffixChars) {
                return false
            }
            for (i in 1..suffixChars) {
                if (suffix[suffixChars - i] != source[existingChars - i]) {
                    return false
                }
            }
            return true
        }

        */
/**
         * If `string` has this suffix, return it as-is; otherwise, return it with this suffix
         * appended.
         *
         * @since 4.8
         *//*

        fun addToIfAbsent(string: String): String {
            return if (string.endsWith(suffix)) string else string + suffix
        }

        */
/**
         * If `builder` does not already have this suffix, append this suffix to it.
         *
         * @return true if this suffix is appended
         * @since 5.7
         *//*

        fun addToIfAbsent(builder: StringBuilder): Boolean {
            val shouldAdd = !isIn(builder)
            if (shouldAdd) {
                builder.append(suffix)
            }
            return shouldAdd
        }

        */
/**
         * Removes this suffix from `builder` if it ends with the suffix.
         *
         * @return true if this suffix is removed
         * @since 5.7
         *//*

        fun removeFrom(builder: StringBuilder): Boolean {
            val present = isIn(builder)
            if (present) {
                builder.delete(builder.length - length, builder.length)
            }
            return present
        }

        */
/**
         * Returns a *view* of `source` with this suffix hidden away if present, or else
         * returns `source` as is.
         *
         * @since 6.5
         *//*

        fun hideFrom(source: String): CharSequence {
            if (isEmpty()) {
                return Objects.requireNonNull(source)
            }
            val match = match(source, 0)
            return match?.preceding() ?: source
        }

        */
/**
         * Replaces this suffix from `builder` with `replacement` if it ends with the
         * suffix.
         *
         * @return true if this suffix is replaced
         * @since 5.7
         *//*

        fun replaceFrom(builder: StringBuilder, replacement: CharSequence): Boolean {
            Objects.requireNonNull(replacement)
            val present = isIn(builder)
            if (present) {
                builder.replace(builder.length - length, builder.length, replacement.toString())
            }
            return present
        }

        */
/** @since 5.7
         *//*

        override fun get(index: Int): Char {
            return suffix[index]
        }

        */
/** @since 5.7
         *//*

        override fun subSequence(start: Int, end: Int): String {
            return suffix.substring(start, end)
        }

        */
/**
         * Returns the length of this suffix.
         *
         * @since 5.7
         *//*

        */
/*override fun length(): Int {
            return suffix.length
        }*//*


        override val length: Int
            get() = suffix.length

        */
/** @since 5.7
         *//*

        override fun hashCode(): Int {
            return suffix.hashCode()
        }

        */
/** @since 5.7
         *//*

        override fun equals(obj: Any?): Boolean {
            return obj is Suffix && suffix == obj.suffix
        }

        */
/** Returns this suffix string.  *//*

        override fun toString(): String {
            return suffix
        }

        override fun match(input: String, fromIndex: Int): SubPatternMatch? {
            val index = input.length - suffix.length
            return if (index >= fromIndex && input.endsWith(suffix)) SubPatternMatch.suffix(
                input,
                suffix.length
            ) else null
        }
    }

    */
/**
     * The result of successfully matching a [SubPattern] against a string, providing access to the
     * [matched substring][.toString], to the parts of the string [before][.before] and
     * [after][.after] it, and to copies with the matched substring [removed][.remove] or
     * [replaced][.replaceWith].
     *
     *
     * *Note:* a [SubPatternMatch] is a view of the original string and holds a strong reference
     * to the original string. It's advisable to construct and use a `Match` object within the
     * scope of a method; holding onto a `Match` object has the same risk of leaking memory as
     * holding onto the string it was produced from.
     *//*

    class SubPatternMatch(
        private val context: String, val startIndex: Int, override val length: Int,
        */
/** When the match fails lookahead or lookbehind conditions, use this index to backtrack.  *//*

        val backtrackIndex: Int, val repetitionStartIndex: Int
    ) : CharSequence {
        val endIndex: Int = startIndex + length

        */
/**
         * While `endIndex` demarcates the matched substring, `repetitionStartIndex` points to
         * the starting point to scan for the succeeding [iteration][SubPattern.iterateIn] of the same
         * pattern. It's by default equal to `endIndex`, but for [Substring.before] and
         * [Substring.upToIncluding], `repetitionStartIndex` starts after the delimiters.
         *//*

        //private val repetitionStartIndex: Int

        init {
            //this.repetitionStartIndex = repetitionStartIndex
            assert(startIndex >= 0) { "Invalid index: $startIndex" }
            assert(length >= 0) { "Invalid length: $length" }
            assert(endIndex <= context.length) { "Invalid endIndex: $endIndex" }
            assert(repetitionStartIndex >= endIndex) { "Invalid repetitionStartIndex: $repetitionStartIndex" }

        }

        */
/**
         * Returns the part of the original string before the matched substring.
         *
         *
         * [.before] and [.after] are almost always used together to split a string into
         * two parts. If you just need the substring before the match, you might want to use `Substring.before(pattern)` instead, because the pattern logic is encoded entirely in the
         * [SubPattern] object. For example:
         *
         * <pre>
         * private static final Substring.Pattern DIRECTORY = Substring.before(last("/"));
        </pre> *
         *//*

        fun before(): String {
            return context.substring(0, startIndex)
        }

        */
/**
         * Returns the part of the original string before the matched substring.
         *
         *
         * [.before] and [.after] are almost always used together to split a string into
         * two parts. If you just need the substring after the match, you might want to use `Substring.after(pattern)` instead, because the pattern logic is encoded entirely in the
         * [SubPattern] object. For example:
         *
         * <pre>
         * private static final Substring.Pattern LINE_COMMENT = Substring.after(first("//"));
        </pre> *
         *//*

        fun after(): String {
            return context.substring(endIndex)
        }

        */
/** Return the full string being matched against.  *//*

        fun fullString(): String {
            return context
        }

        */
/**
         * Returns a copy of the original string with the matched substring removed.
         *
         *
         * This is equivalent to `match.before() + match.after()`.
         *//*

        fun remove(): String {
            // Minimize string concatenation.
            return if (endIndex == context.length) {
                before()
            } else if (startIndex == 0) {
                after()
            } else {
                before() + after()
            }
        }

        */
/**
         * Returns a copy of the original string with the matched substring replaced with `replacement`.
         *
         *
         * This is equivalent to `match.before() + replacement + match.after()`.
         *//*

        fun replaceWith(replacement: CharSequence): String {
            return before() + replacement + after()
        }

        */
/*val isNotEmpty: Boolean
            *//*
*/
/**
             * Returns true if the match isn't empty.
             *
             * @since 6.0
             *//*
*/
/*
            get() = isNotEmpty()*//*


        */
/**
         * Returns an equivalent match with at most `maxChars`.
         *
         * @since 6.1
         *//*

        fun limit(maxChars: Int): SubPatternMatch {
            return if (checkNumChars(maxChars) >= length) this else SubPatternMatch(
                context,
                startIndex, maxChars,
                backtrackIndex, repetitionStartIndex
            )
        }

        */
/**
         * Returns a new instance that's otherwise equivalent except with `fromBeginning`
         * characters skipped from the beginning and `fromEnd` characters skipped from the end.
         * If there are fewer characters, an empty match is returned.
         *
         *
         * For example, `first("hello").in("say hello").get().skip(2, 1)` returns "ll".
         *
         * @since 6.1
         *//*

        fun skip(fromBeginning: Int, fromEnd: Int): SubPatternMatch {
            checkNumChars(fromBeginning)
            checkNumChars(fromEnd)
            if (fromBeginning >= length) {
                return SubPatternMatch(context, endIndex, 0, backtrackIndex, repetitionStartIndex)
            }
            val index = startIndex + fromBeginning
            if (fromEnd >= length - fromBeginning) {
                return SubPatternMatch(context, index, 0, backtrackIndex, repetitionStartIndex)
            }
            val len = length - fromBeginning - fromEnd
            return SubPatternMatch(context, index, len, backtrackIndex, repetitionStartIndex)
        }

        */
/** Return 0-based index of this match in [.fullString].  *//*

        fun index(): Int {
            return startIndex
        }

        */
/**
         * Equivalent to `toString().equals(str)` but without copying the characters into a
         * temporary string.
         *
         * @since 7.1
         *//*

        fun contentEquals(str: String): Boolean {
            return str.length == length && context.startsWith(str, startIndex)
        }

        */
/**
         * Returns true if this match starts with the given `prefix`.
         *
         * @since 7.0
         *//*

        fun startsWith(prefix: String): Boolean {
            return prefix.length <= length && context.startsWith(prefix, startIndex)
        }

        */
/**
         * Returns true if this match ends with the given `suffix`.
         *
         * @since 7.0
         *//*

        fun endsWith(suffix: String): Boolean {
            return suffix.length <= length && context.startsWith(suffix, endIndex - suffix.length)
        }

        */
/**
         * Returns true if the match is immediately followed by the `lookahead` string. Note that
         * `isFollowedBy("")` is always true.
         *//*

        fun isFollowedBy(lookahead: String): Boolean {
            return context.startsWith(lookahead, endIndex)
        }

        */
/**
         * Returns true if the match immediately follows the `lookbehind` string. Note that `isPrecededBy("")` is always true.
         *//*

        fun isPrecededBy(lookbehind: String): Boolean {
            return context.startsWith(lookbehind, startIndex - lookbehind.length)
        }

        */
/**
         * Returns true if the match immediately follows the `lookbehind` string and is
         * immediately followed by the `lookahead` string. Note that `isBetween("", "")` is
         * always true.
         *//*

        fun isImmediatelyBetween(lookbehind: String, lookahead: String): Boolean {
            return isPrecededBy(lookbehind) && isFollowedBy(lookahead)
        }

        fun isSeparatedBy(separatorBefore: CharPredicate, separatorAfter: CharPredicate): Boolean {
            return ((startIndex == 0 || separatorBefore.test(context[startIndex - 1]))
                    && (endIndex >= context.length || separatorAfter.test(context[endIndex])))
        }

        */
/** Returns the length of the matched substring.  *//*

        */
/*override fun length(): Int {
            return endIndex - startIndex
        }*//*


        */
/**
         * {@inheritDoc}
         * @since 4.6
         *//*

        override fun get(index: Int): Char {
            if (index < 0) {
                throw IndexOutOfBoundsException("Invalid index ($index) < 0")
            }
            if (index >= length) {
                throw IndexOutOfBoundsException(
                    "Invalid index ($index) >= length ($length)"
                )
            }
            return context[startIndex + index]
        }

        */
/**
         * Returns a [CharSequence] instance which is a sub-range of this `Match`.
         *
         *
         * For example, if this `Match` points to the range of `"wood"` from
         * the `"Holywood"` string, calling `subSequence(1, 3)` will point to the
         * range of `"oo"` from the original string.
         *
         *
         * Can be used to further reduce the matched range manually.
         *
         * @since 4.6
         *//*

        override fun subSequence(begin: Int, end: Int): CharSequence {
            if (begin < 0) {
                throw IndexOutOfBoundsException("Invalid index: begin ($begin) < 0")
            }
            if (end > length) {
                throw IndexOutOfBoundsException(
                    "Invalid index: end ($end) > length ($length)"
                )
            }
            if (begin > end) {
                throw IndexOutOfBoundsException(
                    "Invalid index: begin ($begin) > end ($end)"
                )
            }
            return SubPatternMatch(
                context, startIndex + begin, end - begin, Int.MAX_VALUE, repetitionStartIndex
            )
        }

        */
/** Returns the matched substring.  *//*

        override fun toString(): String {
            return context.substring(startIndex, endIndex)
        }

        fun following(): SubPatternMatch {
            return suffix(context, context.length - endIndex)
        }

        fun preceding(): SubPatternMatch {
            return nonBacktrackable(context, 0, startIndex)
        }

        */
/**
         * Expands this match for `toLeft` characters before the starting index and `toRight` characters beyond the end index.
         *
         * @throws IllegalArgumentException if either `toLeft` or `toRight` is negative
         * @throws IllegalStateException if there are not sufficient characters to expand
         *//*

        fun expand(toLeft: Int, toRight: Int): SubPatternMatch {
            //assert(toLeft >= 0) { "Invalid toLeft: $toLeft" }
            //assert(toRight >= 0) { "Invalid toRight: $toRight" }
            val newStartIndex = startIndex - toLeft
            val newLength = length + toLeft + toRight
            val newEndIndex = newStartIndex + newLength
            val newRepetitionStartIndex = max(repetitionStartIndex, newEndIndex)
            return SubPatternMatch(
                context, newStartIndex, newLength,
                backtrackIndex, newRepetitionStartIndex
            )
        }

        fun trim(): SubPatternMatch {
            var left = startIndex
            var right = endIndex - 1
            while (left <= right) {
                if (context[left].isWhitespace()) {
                    left++
                    continue
                }
                if (context[right].isWhitespace()) {
                    right--
                    continue
                }
                break
            }
            val trimmedLength = right - left + 1
            return if (trimmedLength == length) this else SubPatternMatch(
                context, left, trimmedLength,
                backtrackIndex, repetitionStartIndex
            )
        }

        fun toEnd(): SubPatternMatch {
            return if (endIndex == context.length) this else suffix(
                context,
                context.length - startIndex
            )
        }

        fun backtrackFrom(fromIndex: Int): Int {
            check(backtrackIndex > fromIndex) { "Not true that $backtrackIndex > $fromIndex" }
            return backtrackIndex
        }

        companion object {
            fun suffix(context: String, length: Int): SubPatternMatch {
                return nonBacktrackable(context, context.length - length, length)
            }

            fun backtrackable(
                backtrackingOffset: Int,
                context: String,
                fromIndex: Int,
                length: Int
            ): SubPatternMatch {
                return SubPatternMatch(
                    context,
                    fromIndex,
                    length,
                    fromIndex + backtrackingOffset,
                    fromIndex + max(1, length)
                )
            }

            fun nonBacktrackable(context: String, fromIndex: Int, length: Int): SubPatternMatch {
                return SubPatternMatch(
                    context,
                    fromIndex,
                    length,
                    Int.MAX_VALUE,
                    fromIndex + max(1, length)
                )
            }
        }
    }

    */
/**
     * The style of the bounds of a match. See [Substring.SubPattern.immediatelyBetween].
     *
     * @since 7.0
     *//*

    enum class BoundStyle {
        */
/** The match includes the bound  *//*

        INCLUSIVE,

        */
/** The match doesn't include the bound  *//*

        EXCLUSIVE
    }

    internal abstract class Last : SubPattern() {
        abstract fun match(input: String, fromIndex: Int, endIndex: Int): SubPatternMatch?
        override fun match(input: String, fromIndex: Int): SubPatternMatch? {
            return match(input, fromIndex, input.length)
        }

        override fun separatedBy(
            separatorBefore: CharPredicate,
            separatorAfter: CharPredicate
        ): SubPattern {
            Objects.requireNonNull<Any>(separatorBefore)
            Objects.requireNonNull<Any>(separatorAfter)
            return look { subPatternMatch: SubPatternMatch ->
                subPatternMatch.isSeparatedBy(
                    separatorBefore,
                    separatorAfter
                )
            }
        }

        override fun lookaround(lookbehind: String, lookahead: String): SubPattern {
            return look { subPatternMatch: SubPatternMatch ->
                subPatternMatch.isImmediatelyBetween(
                    lookbehind,
                    lookahead
                )
            }
        }

        override fun negativeLookaround(lookbehind: String, lookahead: String): SubPattern {
            return look { subPatternMatch: SubPatternMatch ->
                !subPatternMatch.isImmediatelyBetween(
                    lookbehind,
                    lookahead
                )
            }
        }

        private fun look(condition: Predicate<SubPatternMatch>): SubPattern {
            val original = this
            return object : Last() {
                override fun match(input: String, fromIndex: Int, endIndex: Int): SubPatternMatch? {
                    var i = endIndex
                    while (i >= fromIndex) {
                        val match = original.match(input, fromIndex, i)
                        i = if(match!=null) {
                            if (condition.test(match)) {
                                return match
                            }
                            min(match.endIndex - 1, i - 1)
                        } else {
                            i - 1
                        }
                    }
                    return null
                }
            }
        }
    }
}


fun interface CharPredicate {
    */
/** Returns true if `ch` satisfies this predicate.  *//*

    fun test(ch: Char): Boolean

    */
/**
     * Returns a [CharPredicate] that evaluates true if either this or `that` predicate
     * evaluate to true.
     *//*

    fun or(that: CharPredicate): CharPredicate {
        val me = this
        return object : CharPredicate {
            override fun test(c: Char): Boolean {
                return me.test(c) || that.test(c)
            }

            override fun toString(): String {
                return "$me | $that"
            }
        }
    }

    */
/**
     * Returns a [CharPredicate] that evaluates true if both this and `that` predicate
     * evaluate to true.
     *//*

    fun and(that: CharPredicate): CharPredicate {
        val me = this
        return object : CharPredicate {
            override fun test(c: Char): Boolean {
                return me.test(c) && that.test(c)
            }

            override fun toString(): String {
                return "$me & $that"
            }
        }
    }

    */
/**
     * Returns a [CharPredicate] that evaluates true if either this predicate evaluates to true,
     * or the character is `ch`.
     *//*

    fun or(ch: Char): CharPredicate {
        return or(`is`(ch))
    }

    */
/**
     * Returns a [CharPredicate] that evaluates true if either this predicate evaluates to true,
     * or the character is in the range of `[from, to]`.
     *//*

    fun orRange(from: Char, to: Char): CharPredicate {
        return or(range(from, to))
    }

    */
/** Returns the negation of this `CharPredicate`.  *//*

    operator fun not(): CharPredicate {
        val me = this
        return object : CharPredicate {
            override fun test(c: Char): Boolean {
                return !me.test(c)
            }

            override fun toString(): String {
                return "not ($me)"
            }
        }
    }

    */
/**
     * Returns `true` if a character sequence contains at least one matching BMP character.
     * Equivalent to `!matchesNoneOf(sequence)`.
     *
     * @since 7.0
     *//*

    fun matchesAnyOf(sequence: CharSequence): Boolean {
        return !matchesNoneOf(sequence)
    }

    */
/**
     * Returns `true` if a character sequence contains only matching BMP characters.
     *
     * @since 7.0
     *//*

    fun matchesAllOf(sequence: CharSequence): Boolean {
        for (i in sequence.length - 1 downTo 0) {
            if (!test(sequence[i])) {
                return false
            }
        }
        return true
    }

    */
/**
     * Returns `true` if a character sequence contains no matching BMP characters. Equivalent to
     * `!matchesAnyOf(sequence)`.
     *
     * @since 7.0
     *//*

    fun matchesNoneOf(sequence: CharSequence): Boolean {
        for (i in sequence.length - 1 downTo 0) {
            if (test(sequence[i])) {
                return false
            }
        }
        return true
    }

    companion object {
        */
/** Equivalent to the `[a-zA-Z]` character class.  *//*

        val ALPHA = range('a', 'z').orRange('A', 'Z')

        */
/** Equivalent to the `[a-zA-Z0-9_]` character class.  *//*

        val WORD = ALPHA.orRange('0', '9').or('_')

        */
/** Corresponds to the ASCII characters.  *//*

        val ASCII: CharPredicate = object : CharPredicate {
            override fun test(c: Char): Boolean {
                return c <= '\u007f'
            }

            override fun toString(): String {
                return "ASCII"
            }
        }

        */
/** Corresponds to all characters.  *//*

        val ANY: CharPredicate = object : CharPredicate {
            override fun test(c: Char): Boolean {
                return true
            }

            override fun toString(): String {
                return "ANY"
            }
        }

        */
/** Corresponds to no characters.  *//*

        val NONE: CharPredicate = object : CharPredicate {
            override fun test(c: Char): Boolean {
                return false
            }

            override fun toString(): String {
                return "NONE"
            }
        }

        */
/** Returns a CharPredicate for the range of characters: `[from, to]`.  *//*

        fun `is`(ch: Char): CharPredicate {
            return object : CharPredicate {
                override fun test(c: Char): Boolean {
                    return c == ch
                }

                override fun toString(): String {
                    return "'$ch'"
                }
            }
        }

        */
/** Returns a CharPredicate for the range of characters: `[from, to]`.  *//*

        fun range(from: Char, to: Char): CharPredicate {
            return object : CharPredicate {
                override fun test(c: Char): Boolean {
                    return c >= from && c <= to
                }

                override fun toString(): String {
                    return "['$from', '$to']"
                }
            }
        }

        */
/** Returns a CharPredicate that matches any of `chars`.  *//*

        fun anyOf(chars: String): CharPredicate {

            return object : CharPredicate {
                override fun test(c: Char): Boolean {
                    return chars.indexOf(c) >= 0
                }

                override fun toString(): String {
                    return "anyOf('$chars')"
                }
            }
        }

        */
/** Returns a CharPredicate that matches any of `chars`.  *//*

        fun noneOf(chars: String): CharPredicate {

            return object : CharPredicate {
                override fun test(c: Char): Boolean {
                    return chars.indexOf(c) < 0
                }

                override fun toString(): String {
                    return "noneOf('$chars')"
                }
            }
        }
    }
}

fun <T> whileNotNull(supplier: Supplier<out T?>): Stream<T> {
    return StreamSupport.stream<T>(
        object : Spliterator<T> {
            override fun tryAdvance(action: Consumer<in T>): Boolean {
                val generated: T = supplier.get()?:return false
                action.accept(generated)
                return true
            }

            override fun characteristics(): Int {
                return Spliterator.NONNULL or Spliterator.ORDERED
            }

            override fun estimateSize(): Long {
                return Long.MAX_VALUE
            }

            override fun trySplit(): Spliterator<T>? {
                return null
            }
        },
        false
    )
}*/
